/*
 * startup.c
 *
 * Created: 8/16/2011 1:14:13 PM
 *  Author: t-kagu
 */ 
#include <asf.h>
#include "conf_board.h"
#include "conf_startup.h"
#include "twi_pdca.h"
#include "conf_pdca.h"
#include "usart1_pdca.h"

void startup()
{
	/*Set device clock to 66mhz*/	
	sysclk_init();
	
	// Initialize the ASF delay (delay_ms(), delay_us(), etc.) services.
	delay_init(sysclk_get_cpu_hz());
	
	delay_ms(500);
	
	/*enable dma*/
	sysclk_enable_hsb_module(SYSCLK_PDCA_HSB);
	
	/*enable timer/counter*/
	sysclk_enable_pba_module(SYSCLK_TC);
	
	/*enable pwm*/
	sysclk_enable_pba_module(SYSCLK_PWM);
	
	
	/*DISABLED, no 32khz clock right now, next hardware iteration*/
	//osc_enable(OSC_ID_OSC32);
	//osc_wait_ready(OSC_ID_OSC32);
		
	//init_device_clock();
	
	board_init();
	
	/*enable RTC based on the internal osc..*/
	/*currently using RC osc, shoudl use 32khz, 6 gives 898 hz, or 1.11304348 slower.
	one tick is 1.11304348 mills*/
	//rtc_init(RTC,RTC_OSC_RC,6);
	//rtc_enable(RTC);
	
	//enable interrupts
	Disable_global_interrupt();
	irq_initialize_vectors();
	INTC_init_interrupts();
	Enable_global_interrupt();

	/*init USART 1 for communication with user*/
	init_device_USART1();
	
	/*init i2c-twi*/
	init_device_TWI();	
	
	/*init the PDCA for twi*/
	init_pdca_TWI();	
	
	/*init USART1 DMA*/
	init_pdca_USART1();
	
	/*init the PWM controller*/
	init_PWM();
	
	printf("start up complete\n");
}

void init_device_USART1(void)
{	
	static const gpio_map_t COMM_USART_GPIO_MAP =
	{
		{AVR32_USART1_RXD_0_0_PIN, AVR32_USART1_RXD_0_0_FUNCTION},
		{AVR32_USART1_TXD_0_0_PIN, AVR32_USART1_TXD_0_0_FUNCTION}
	};
   
	// Assign GPIO to USART
	gpio_enable_module(COMM_USART_GPIO_MAP, sizeof(COMM_USART_GPIO_MAP) / sizeof(COMM_USART_GPIO_MAP[0]));
	
	// Initialize USART in RS232 mode.
	static usart_serial_options_t USART_SERIAL_OPTIONS = 
	{ 
		.baudrate     = CONFIG_USART_BAUDRATE,
		.charlength   = CONFIG_USART_CHAR_LENGTH,
		.paritytype   = CONFIG_USART_PARITY,
		.stopbits     = CONFIG_USART_STOP_BIT, 
	};
	
	/*stdio shoudl go to usart*/
	stdio_serial_init(&CONFIG_USART_IF, &USART_SERIAL_OPTIONS);
	
	// Specify that stdout and stdin should not be buffered.
	setbuf(stdout, NULL);
	setbuf(stdin,  NULL);
}


/*init the TWI first*/
void init_device_TWI(void)
{		
	/*confgiure the GPIO pins for TWI*/
	static const gpio_map_t TWI_GPIO_MAP =
	{
		{AVR32_TWI_SDA_0_0_PIN, AVR32_TWI_SDA_0_0_FUNCTION},
		{AVR32_TWI_SCL_0_0_PIN, AVR32_TWI_SCL_0_0_FUNCTION}
	};

	gpio_enable_module(TWI_GPIO_MAP, sizeof(TWI_GPIO_MAP) / sizeof(TWI_GPIO_MAP[0]));

	/*setup TWI*/
	twi_master_options_t master_opt =
	{
		 .speed = TWI_SPEED,
		 .chip  = 0,
	};
	
	twi_master_disable(&AVR32_TWI);
	twi_master_enable(&AVR32_TWI);
	
	twi_master_setup(&AVR32_TWI,&master_opt);
}


/*Initializes the PDCA for TWI, sets up the interrupt also*/
void init_pdca_TWI(void)
{		
    // PDCA channel options 
    static const pdca_channel_options_t PDCA_RX_OPTIONS = 
    { 
      .addr = (void *)0x0,            // memory address 
      .pid = AVR32_PDCA_PID_TWI_RX,              // select peripheral - data are transmit on USART TX line. 
      .size = 0,       // transfer counter 
      .r_addr = NULL,                           // next memory address 
      .r_size = 0,                              // next transfer counter 
	  .transfer_size = PDCA_TRANSFER_SIZE_BYTE  // select size of the transfer 
    }; 
	
	/*init's the pdca channel with twi_channel*/
    twi_master_pdca_init(TWI_PDCA_CHANNEL,&PDCA_RX_OPTIONS);
}

/*init 4 PWM channels for 400HZ servo transmission, for quadrotor only*/
void init_PWM(void)
{
	/*config PWM ouputs to be 400 HZ
	(66mhz / 66/2500)*/
	
	pwm_opt_t pwm_opt =
	{
		.diva = 66,
		.divb = AVR32_PWM_DIVB_CLK_OFF,
		.prea = AVR32_PWM_PREA_MCK,
		.preb = AVR32_PWM_PREB_MCK,
	};                     
	
	// PWM option config.  
	// With these settings, the output waveform period will be :
	// (66000000/66)/2500 == 400Hz == (MCK/prescaler)/period, with MCK == 66000000hz,
	// prescaler == 66, period == 2500.
	avr32_pwm_channel_t pwm_channel = 
	{ 
		.ccnt = 0,
		.cdty = 1100,   // Channel duty cycle, should be < CPRD. //starting of servo wave
		.cprd = 2500,  // Channel period.
		.cupd = 0,   // Channel update is not used here.
	};  // One channel config.
	pwm_channel.CMR.calg = PWM_MODE_LEFT_ALIGNED;       // Channel mode.
	pwm_channel.CMR.cpol = PWM_POLARITY_HIGH;            // Channel polarity.
	pwm_channel.CMR.cpd = PWM_UPDATE_DUTY;              // Not used the first time, BUT SETS UPDATES TO DUTY CYCLE
	pwm_channel.CMR.cpre = AVR32_PWM_CPRE_CLKA;  // Channel prescaler.
	
	static const gpio_map_t PWM_GPIO_MAP =
	{
		{AVR32_PWM_0_PIN, AVR32_PWM_0_FUNCTION},
		{AVR32_PWM_1_PIN, AVR32_PWM_1_FUNCTION},
		{AVR32_PWM_2_PIN, AVR32_PWM_2_FUNCTION},
		{AVR32_PWM_3_PIN, AVR32_PWM_3_FUNCTION}
	};
   
	// Assign GPIO to USART
	gpio_enable_module(PWM_GPIO_MAP, sizeof(PWM_GPIO_MAP) / sizeof(PWM_GPIO_MAP[0]));
	
	/*init PWM*/
	pwm_init(&pwm_opt);
	
	/*channel id - 0*/
	pwm_channel_init(0,&pwm_channel);
	pwm_channel_init(1,&pwm_channel);
	pwm_channel_init(2,&pwm_channel);
	pwm_channel_init(3,&pwm_channel);
	
	pwm_start_channels(0x0F);
	
}	
